import json
import os

import numpy as np
import matplotlib.pyplot as plt
import openpyxl




# 1. 按单元格比较
# 改良前面的，对每个单元格的数据进行比较   20211203之后
# 参与比较的是myresults/XX.json与BESTofCELL.json文件
# 生成的会是一个json文件rank.json，模型名XX：113*20的列表
# 如果我的XX.json的某个网格的较大，那么rank.json中为1，否则为0。
import json
def convert2list11320(jsondata:list):
    '''将excel生成的json数据转换成113*20列表'''
    lst = [list(row.values()) for row in jsondata]
    return lst

def appendCELLbest():
    # 这个是手工制作的，用\t分割的json,值还是粘在一起的
    with open("../base/" + basefname, "r", encoding="utf8") as f:
        data = json.loads(f.read())
        data = convert2list11320(data)
        return data
def append_my(name):
    # 这个是手工制作的，用\t分割的json,值还是粘在一起的
    with open(name,"r",encoding="utf8") as f:
        data = json.loads(f.read())
        data = convert2list11320(data)
        return data
def let_myBEST_21():
    # 对113*20的小格子，如果我的指 标是最好的，就让它成为1(to1)
    import os
    file_names = os.listdir("myresults")
    # file_names.sort(key=lambda x:int(x.split('(')[0]))

    # 下面都是自动执行的
    metrics = ['sen', 'me', 'mse(small)', 'avg', 'std', 'vifp', 'snr', 'min', 'uqi', 'qabf', 'vif', 'ssim', 'psnr', 'ifc', 'q0i', 'ce(small)', 'edge', 'qcv(small)', 'sf', 'qcb']
    #  把自己的模型和指标平均值添加一下
    best = appendCELLbest()    # 是一个113*20
    results = {}

    sel_model_and_pics = {}
    for name in file_names:
        my = append_my("myresults/" + name)


        sel_picNo = []

        best113 = []      # 结果会是一个列表，对应每个图片的指标是不是最佳
        # 还应该有一个，每个图片，
        for i in range(113):    # 循环一个json文件
            row_best = []       # row_best存下一个json表的一行的0和1
            for j,m in enumerate(metrics):
                if "small" not in m :
                    if my[i][j] >= best[i][j] :
                        row_best.append(1)
                    else:
                        row_best.append(0)
                else:
                    if my[i][j] <= best[i][j] :
                        row_best.append(1)
                    else:
                        row_best.append(0)
            best113.append(row_best)

            if sum(row_best) >= needBESTnum:       # 如果这个图片可以使3个指标最优，那就保留作为选中的数据集（也可以改成4,5，。。。）
                sel_picNo.append(i+1)

        results[name[:-5]]=best113      # 如3(4080).json文件，取出名字为键，best113存下一个json表的每个位置的0和1
        if len(sel_picNo) >= needPICnum:        # 如果有25张图片都有3个最优指标，那么，就把这个{模型名:图像编号}保存下来
            sel_model_and_pics[name[:-5]] = sorted(sel_picNo)

    with open("./rank.json","w",encoding="utf8") as f:
        f.write(json.dumps(results))
    with open("./prime_pics.json","w",encoding="utf8") as f:
        f.write(json.dumps(sel_model_and_pics))
# let_myBEST_21()
# print("OK")


# 3. 将2中的json文件可视化为rank.xlsx文件，其中如果某个图某指标是最好的，那么该位置染色并置为1.否则，只写个0
def makeCELLxlsx():
    "用于将结果保存在excel中，方便分析"

    base_path = "./"
    path = "./rank.json"
    with open(path, "r", encoding="utf8") as f:
        data = json.loads(f.read())

    from openpyxl.styles import PatternFill
    style = PatternFill("solid", fgColor="73ff34")

    # 创建新表
    new_wb = openpyxl.Workbook()
    for i, (name, best113) in enumerate(data.items()):
        new_sheet = new_wb.create_sheet(title=name)
        # 添加标题
        metrics = ['sen', 'me', 'mse(small)', 'avg', 'std', 'vifp', 'snr', 'min', 'uqi', 'qabf', 'vif', 'ssim', 'psnr',
                   'ifc', 'q0i', 'ce(small)', 'edge', 'qcv(small)', 'sf', 'qcb',"求和"]
        new_sheet.append(metrics)

        # 添加源数据
        for index,row_best in enumerate(best113):
            row_best.append(f"=SUM(A{index+2}:T{index+2})")
            new_sheet.append(row_best)

            for colN,best in enumerate(row_best[:-1]):    # 加这个循环是为了染色
                if best:
                    new_sheet[f"{chr(ord('A') + colN)}{index+2}"].fill = style  # 填充单元格

        # 最后一行求平均值
        avg_formula = [f"=SUM({chr(ord('A') + off)}2:{chr(ord('A') + off)}116)" for off in range(ord('T')-ord('A')+1)]
        new_sheet.append(avg_formula)

        # xlsx_path = base_path + "rank.xlsx"
        xlsx_path = base_path + "rank.xlsx"
        new_wb.save(xlsx_path)  # 写入,保存为模型名

# makeCELLxlsx()
#
# print("OK")


# 4. 在上一步的基础上，在表中的第一页统计，每个模型分别有几张照片是最好的。（选什么数据集要用）
def writCELLsheetcmp():

    file_name = './rank.xlsx'
    wb = openpyxl.load_workbook(file_name)
    sheet = wb["Sheet"]

    thead = ["模型名", "5个最好","4个最好","3个最好"]
    sheet.append(thead)

    for name in wb.sheetnames[1:]:
        row = [name]
        row.extend([f"""=COUNTIF('{name}'!U2:'{name}'!U116,">={i}")""" for i in [5,4,3]])
        sheet.append(row)
    wb.save(file_name)
# writCELLsheetcmp()
# print("OK")



# 4. 将大于3个最优指标的图像行（保存在prime_pics中）那个抽出来
def extractPrimeRowsAndCmp():
    import json
    import openpyxl

    def write_cmp_sheet(new_wb, sheet_names, avg_row_pos):
        cmp_sheet = new_wb["cmp"]

        for index, name in enumerate(sheet_names):
            if not index:  # 添加表名,这个应该是叫Sheet的空表单
                m = ["model"]
                for cell in new_wb[name][1]:
                    m.append(cell.value)
                cmp_sheet.append(m)

            avg_from = [name]
            avg_from.extend([f"='{name}'!{chr(ord('A') + off)}{avg_row_pos}" for off in
                             range(ord('T') - ord('A') + 1)])
            cmp_sheet.append(avg_from)  # 新sheet添加原表数据

    def write_others_xlsx(new_wb, rows):
        # 打开比较的模型数据
        # file_name = "D:/matlab_work/fusion_metrix_results/baseXLSX/29.xlsx"
        file_name = srcMTXfile
        wb = openpyxl.load_workbook(file_name)  # 打开文件

        temp_others_name = []

        # 迭代每个sheet,进行取特定行的操作，写入新表
        for sheet in wb:
            temp_others_name.append(sheet.title)
            new_sheet = new_wb.create_sheet(title=sheet.title)  # 新表中创建同名sheet

            # 取源数据。列名的第一行,这儿就不用再次插入了
            for r in rows:
                r_data = []
                for cell in sheet[r]:  # sheet是原表
                    r_data.append(cell.value)
                new_sheet.append(r_data)  # 新sheet添加原表数据

            # 最后一行求平均值
            avg_formula = [f"=AVERAGE({chr(ord('A') + off)}2:{chr(ord('A') + off)}{len(rows)})" for off in
                           range(ord('T') - ord('A') + 1)]
            new_sheet.append(avg_formula)

        return temp_others_name
    def make_xlsx():
        "把优势图片的行抽出来，放到一个新的表中"
        # 获取自己的模型名和优势图片编号
        base_path = "./"
        with open(base_path + "prime_pics.json", "r", encoding="utf8") as f:
            data = json.loads(f.read())

        # 打开自己的mytestG7依次操作,wb:我的结果
        # file_name = "D:/matlab_work/fusion_metrix_results/mytestG7ALL.xlsx"
        file_name = srcMTXfile
        wb = openpyxl.load_workbook(file_name)  # 打开文件,read_only设置为True，则无法按列访问单元格。

        # 根据自己的较好的模型的模型名,进行操作
        for name, rows in data.items():
            sheet = wb[name]  # 选中sheet

            # 创建新表
            new_wb = openpyxl.Workbook()
            new_sheet = new_wb.create_sheet(title=name)

            # 取源数据
            rows = list(map(lambda x: x + 1, rows))  # 因为图片行数是从第2行开始的，而图片名是从1开始的。
            rows.insert(0, 1)  # 这是列名的第一行
            for r in rows:
                r_data = []
                for cell in sheet[r]:
                    r_data.append(cell.value)
                new_sheet.append(r_data)

            # 最后一行求平均值
            avg_formula = [f"=AVERAGE({chr(ord('A') + off)}2:{chr(ord('A') + off)}{len(rows)})" for off in
                           range(ord('T') - ord('A') + 1)]
            new_sheet.append(avg_formula)

            # 再把参照模型的数据都进行一下写入
            sheet_names  = write_others_xlsx(new_wb, rows)

            # 先保存文件，再加载，写入cmp的值
            new_wb["Sheet"].title = 'cmp'
            # 再将比较数据放在首页
            sheet_names.append(name)
            write_cmp_sheet(new_wb, sheet_names, len(rows) + 1)

            xlsx_path = base_path + name + ".xlsx"
            new_wb.save(xlsx_path)  # 写入,保存为模型名

        wb.close()

    # 将prime_pics.json中的模型的优势图片挑出来,并将这些图片用于其他NN模型模型,将两者的结果放在一起比较
    make_xlsx()


# extractPrimeRowsAndCmp()
# print("OK")

# 运行此模块，会将每张图片每个指标的最优模型选出，如果我的模型是第一，那就标为1；
# 模型的结果是一个excel，其中各表单是模型名
# 还会生成若干图片，是以像素为点，表示是否是第一。
if __name__=="__main__":
    # 这里设置两个参数
    basefname = "BEST9nn.json"
    srcMTXfile = r"D:\cycleFusion-project\msrs-113\metrics\cmp1\Extract7nn/extractFile7nn20Td.xlsx"  # 这个里面需要包含CycleFusion
    needBESTnum = 2
    needPICnum = 21


    # # 1.先生成primepics
    # let_myBEST_21()
    # makeCELLxlsx()
    # writCELLsheetcmp()

    # 2.如果数量够多（优势图片中有值），再进行此操作：抽取，比较
    extractPrimeRowsAndCmp()


    print("ok")


# 这儿需要先手动将值传递至result.xlsx之后,再调用下面这个函数
# set_condition_format3()